#include "media_sys.h"
int time_up_down = 1;

MEDIA_POI Media_Sys_Init()//项目初始化  --- 硬件设备初始化
{

    MEDIA_POI mp = (MEDIA_POI)malloc(sizeof(MEDIA_STR));
    if(mp == (MEDIA_POI)NULL)
    {
        perror("malloc ...");
        return (MEDIA_POI)-1;
    }

    memset(mp,0,sizeof(MEDIA_STR));

    //初始化LCD硬件资源
    if((mp->lcd = open(LCD_DEV_PATH,O_RDWR)) == -1)
    {
        perror("open ...");
        return (MEDIA_POI)-1;
    }

    //获取LCD 的 w 和 h
    struct fb_var_screeninfo var;
    //ioctl 获取 fB0对应的LCD 的宽和高
    if(ioctl(mp->lcd,FBIOGET_VSCREENINFO,&var) == -1)
    {
        perror("ioctl ...");
        return (MEDIA_POI)-1;
    }
    else
    {
        mp->lcd_w = var.xres;
        mp->lcd_h = var.yres;
        printf("LCDw:%d----LCDh:%d\n",mp->lcd_w,mp->lcd_h);
    }


    // 根据显存大小去映射
    if((mp->mmap_start_poi = (int *)mmap(NULL,mp->lcd_w*mp->lcd_h*LCD_PIXEL_SIZE,PROT_READ | PROT_WRITE,MAP_SHARED,mp->lcd,0)) == (int *)MAP_FAILED)
    {
        perror("mmap ...");
        return (MEDIA_POI)-1;
    }


    //初始化触摸屏硬件资源
    if((mp->ts = open(TOUCH_LCD_DEV_PATH,O_RDONLY)) == -1)
    {
        perror("open ...");
        return (MEDIA_POI)-1;
    }

    mp->touch_x = -1;
    mp->touch_y = -1;

    //初始化字符显示
    if((mp->dzk = open(DZK_FILE_PATH,O_RDWR)) == -1)
    {
        perror("open dzk...");
        return false;
    }

    if((mp->dzk_file_size = lseek(mp->dzk,0,SEEK_END)) == -1)
    {
        perror("lseek dzk...");
        return false;
    }

    if(lseek(mp->dzk,0,SEEK_SET) == -1)
    {
        perror("lseek dzk...");
        return false;
    }

    if((mp->dzk_mmap_poi = (char *)mmap(NULL,mp->dzk_file_size,PROT_READ|PROT_WRITE,MAP_SHARED,mp->dzk,0)) == MAP_FAILED)
    {
        perror("mmap lcd...");
        return false;
    }


    //初始化字符显示22222222
    if((mp->dzk2 = open(DZK_FILE_PATH2,O_RDWR)) == -1)
    {
        perror("open dzk...");
        return false;
    }

    if((mp->dzk_file_size2 = lseek(mp->dzk2,0,SEEK_END)) == -1)
    {
        perror("lseek dzk...");
        return false;
    }

    if(lseek(mp->dzk2,0,SEEK_SET) == -1)
    {
        perror("lseek dzk...");
        return false;
    }

    if((mp->dzk_mmap_poi2 = (char *)mmap(NULL,mp->dzk_file_size2,PROT_READ|PROT_WRITE,MAP_SHARED,mp->dzk2,0)) == MAP_FAILED)
    {
        perror("mmap lcd...");
        return false;
    }

    //设置字体颜色 和 背景颜色
    mp->font_color      = 0x00000000;
    mp->broadground_color = 0x00ffffff;

    return mp;
}


bool Start(MEDIA_POI mp)//开始
{
    pthread_t id_1,id_2;

    time_up_down = 1;
    if(pthread_create(&id_2,NULL,pthread_time,mp) != 0)
    {
        perror("pthread_cread_create ...");
        return false;
    }
    Lock_Screen(mp);
    if(Main_Touch_Ctrl(mp) == false)
    {
        printf("主界面触摸屏控制失败！\n");
        return false;
    }
    pthread_join(id_2, NULL);

    return true;
}


bool Show_Ui(MEDIA_POI mp,const char * ui_pic_path)//画界面函数
{
    //打开图片文件 
    int bmp = open(ui_pic_path,O_RDONLY);
    if(bmp == -1)
    {
        perror("open ...");
        return false;
    }

    //获取图片的宽和高
    int bmp_w,bmp_h;
    if(lseek(bmp,18,SEEK_SET) == -1)
    {
        perror("lseek 18...");
        return false;
    }

    if(read(bmp,&bmp_w,sizeof(int)) == -1)
    {
        perror("read bmp_w...");
        return false;
    }

    if(read(bmp,&bmp_h,sizeof(int)) == -1)
    {
        perror("read bmp_h...");
        return false;
    }

    int skip = 0;

    if(bmp_w * BMP_PIXEL_SIZE % 4 !=0)
    {
        skip = 4 - (bmp_w * BMP_PIXEL_SIZE % 4);
    }


    //根据宽和高去定义数组的大小
    char rgb[bmp_w * bmp_h * BMP_PIXEL_SIZE + skip * bmp_h];

    //读取图片的像素点
    if(lseek(bmp,54,SEEK_SET) == -1)
    {
        perror("lseek 54 ...");
        return false;
    }

    if(read(bmp,rgb,bmp_w * bmp_h * BMP_PIXEL_SIZE + skip * bmp_h) == -1)
    {
        perror("read bmp rgb ...");
        return false;
    }



    //循环赋值像素点给映射指针
    for(int y=0,n=0; y<bmp_h; y++)
    {
        for(int x=0; x<bmp_w; x++,n+=3)
        {
            *(mp->mmap_start_poi + mp->lcd_w * (bmp_h-1-y) + x) = \
                                                                rgb[n]   << 0 | 
                                                                rgb[n+1] << 8 | 
                                                                rgb[n+2] << 16;
        }

        n+=skip;
    }


    //关闭图片文件
    if(close(bmp) == -1)
    {
        perror("clsoe ui bmp ...");
        return false;
    }

    return true;
}


bool Get_Touch_Xy(MEDIA_POI mp,int mode)//获取触摸屏坐标
{
    struct input_event touch;
    while(1)
    {
        if(read(mp->ts,&touch,sizeof(touch)) == -1)
        {
            perror("read touch lcd ...");
            return false;
        }

        if(touch.type == EV_ABS && touch.code == ABS_X) mp->touch_x = touch.value;
        if(touch.type == EV_ABS && touch.code == ABS_Y) mp->touch_y = touch.value;

        if (mode == 0) 
        {
            if (touch.type == EV_KEY && touch.code == BTN_TOUCH && touch.value == 0) 
            {
                break;
            }
        }
        else if(mode == 1) 
        {
            if(mp->touch_x > 600 && touch.type == EV_KEY && touch.code == BTN_TOUCH && touch.value == 0)
            {
                break;
            }
            else if(mp->touch_x < 600 ) break;
        }
    }

    return true;
}


bool Main_Touch_Ctrl(MEDIA_POI mp)//主界面触摸控制
{
    while(1)
    {
        //先获取点击的触摸坐标，再去判断坐标是哪个按钮的区间
        if(Get_Touch_Xy(mp,0) == false)
        {
            printf("读取触摸屏坐标失败！\n");
            return false;
        }

        if(mp->touch_x > 45 && mp->touch_x < 253 && mp->touch_y > 281 && mp->touch_y < 452) //相册按钮
        {
            time_up_down = 0;
            if(Album(mp) == false)
            {
                printf("启动相册失败！\n");
                return false;
            }
        }

        if(mp->touch_x > 300 && mp->touch_x < 500 && mp->touch_y > 281 && mp->touch_y < 452) //视频按钮
        {
            time_up_down = 0;
            if(vibum(mp) == false)
            {
                printf("启动视频失败！\n");
                return false;
            }
        }

        if(mp->touch_x > 550 && mp->touch_x < 749 && mp->touch_y > 281 && mp->touch_y < 452) //游戏按钮
        {
            time_up_down = 0;
            if(Game(mp) == false)
            {
                printf("启动游戏失败！\n");
                return false;
            }
        }


        if(mp->touch_x > 700 && mp->touch_x < 800 && mp->touch_y > 0 && mp->touch_y < 100) //退出按钮
        {
            Show_Ui(mp,"/ui/down_ui.bmp");
            time_up_down = -1;
            mp->touch_x = -1;
            mp->touch_y = -1;
            break;
        }
    }

    return true;
}


bool Show_Time(MEDIA_POI mp) // 时间显示
{
    char time[32]={0};
    int h = 23;
    int m = 59;
    int s = 55;

    while(1)
    {
        
        for(;h < 24; m=0)
        {
            for (;m < 60; m++,s=0)
            {
                for (;s < 60; s++)
                {
                    if(time_up_down == -1) goto exti;
                    if(time_up_down == 1)
                    {
                        sprintf(time,"%02d:%02d:%02d",h,m,s);
                        Sentence_Show(time,mp,5,5);
                    }
                    sleep(1);
                }
            }
            h++;
            if(h==24)h=0;
        }      
    }
    exti: return true;
}


void *pthread_time(void *arg)
{
    MEDIA_POI mp = (MEDIA_POI) arg;

    if(Show_Time(mp) == false)
    {
        printf("时间显示失败！\n");
        return (void *)-1;
    }
    return NULL;
}


bool Lcd_Clean(MEDIA_POI mp,int color) //刷指定颜色全屏
{
    for(int y=0; y<mp->lcd_h; y++)
    {
        for(int x=0; x<mp->lcd_w; x++)
        {
            *(mp->mmap_start_poi + mp->lcd_w * y + x) = color;
        }

    }

    return true;
}


bool Ascii_Show(char * font,MEDIA_POI mp,int where_x,int where_y)//显示一个字符
{
    int * new_lcd_mmap = mp->mmap_start_poi + 800*where_y+where_x;

    int font_offset = font[0]*16*16/8;
    char * font_obj_p = mp->dzk_mmap_poi + font_offset;

    for(int y=0; y<16; y++) //表示16行
    {
        for(int x=0; x<2; x++) //每行有2个字节,这循环两次，每次只获取一个字节的 字模数据
        {
            //获取一个字节的字模数据 0x123456
            char type = *(font_obj_p+2*y+x);
            for(int z=0; z<8; z++) //每一个字节 8 位
            {
                if(type & 0x80>>z) //0x80就是二进制的10000000
                {
                    //字体颜色
                    *(new_lcd_mmap + 800*y+(8*x+z)) = mp->font_color;
                }
                else
                {
                    //背景颜色
                    *(new_lcd_mmap + 800*y+(8*x+z)) = mp->broadground_color;
                }
            }
        }
    }    

    return true;
}


bool Sentence_Show(char * sentence,MEDIA_POI mp,int where_x,int where_y)//显示一句
{
    for (int index = 0; index < strlen(sentence); index+=1)
    {
        if (Ascii_Show(sentence+index,mp,where_x,where_y) == false)
        {
            printf("显示句子失败！\n");
            return false;
        }
        
        where_x +=9;
        if (where_x >= 770)
        {
            where_x = 0;
            where_y += 18;
        }
        
        
    }
    return true;
}


bool Ascii50_Show(char * font,MEDIA_POI mp,int where_x,int where_y)//显示一个48字符
{
    int * new_lcd_mmap = mp->mmap_start_poi + 800*where_y+where_x;

    int font_offset = font[0]*48*48/8;
    char * font_obj_p = mp->dzk_mmap_poi2 + font_offset;

    for(int y=0; y<48; y++) //表示48行
    {
        for(int x=0; x<6; x++) //每行有6个字节,这循环两次，每次只获取一个字节的 字模数据
        {
            //获取一个字节的字模数据 0x123456
            char type = *(font_obj_p+6*y+x);
            for(int z=0; z<8; z++) //每一个字节 8 位
            {
                if(type & 0x80>>z) //0x80就是二进制的10000000
                {
                    //字体颜色
                    *(new_lcd_mmap + 800*y+(8*x+z)) = mp->font_color;
                }
                else
                {
                    //背景颜色
                    *(new_lcd_mmap + 800*y+(8*x+z)) = mp->broadground_color;
                }
            }
        }
    }    

    return true;
}


bool Sentence_Show_50(char * sentence,MEDIA_POI mp,int where_x,int where_y)//显示一句48
{
    for (int index = 0; index < strlen(sentence); index+=1)
    {
        if (Ascii50_Show(sentence+index,mp,where_x,where_y) == false)
        {
            printf("显示句子失败！\n");
            return false;
        }
        
        where_x +=48;
        if (where_x >= 770)
        {
            where_x = 0;
            where_y += 55;
        }
        
        
    }

    return true;
}


bool Lock_Screen(MEDIA_POI mp)//锁屏
{
    Show_Ui(mp,"/ui/Lock_Screen.bmp");

    for (int y = 200; y < 250; y++)
    {
        for (int x = 200; x < 550; x++)
        {
            if(x<250)
            {
                int index = y * mp->lcd_w + x;
                *(mp->mmap_start_poi + index) = 0xffffff;
            }
            else
            {
                int index = y * mp->lcd_w + x;
                *(mp->mmap_start_poi + index) = 0x000000;
            }
        }
    }
    while(1)
    {
        if(Get_Touch_Xy(mp,1) == false)
        {
            printf("读取触摸屏坐标失败！\n");
            return false;
        }

        if (mp->touch_x > 550 && mp->touch_x < 560 && mp->touch_y > 200 && mp->touch_y < 250)
        {
            break;
        }
        if (mp->touch_x > 250 && mp->touch_x < 550 && mp->touch_y > 200 && mp->touch_y < 250)
        {
            for (int y = 200; y < 250; y++)
            {
                for (int x = 250; x < 550; x++)
                {
                    if(x<mp->touch_x)
                    {
                        int index = y * mp->lcd_w + x;
                        *(mp->mmap_start_poi + index) = 0xffffff;
                    }
                    else
                    {
                        int index = y * mp->lcd_w + x;
                        *(mp->mmap_start_poi + index) = 0x000000;
                    }
                }
            }
        }
    }
    //在这里显示主界面
    if(Show_Ui(mp,"/ui/main_ui.bmp") == false)
    {
        printf("显示主界面失败！\n");
        return (MEDIA_POI)-1;
    }
    return true;
}


bool Media_Sys_Free(MEDIA_POI mp)//项目结束释放 --- 硬件设备结束释放
{
    //显示退出界面
    if(Show_Ui(mp,"/ui/exit.bmp") == -1)
    {
        printf("显示退出界面失败！\n");
        return false;
    }

    if(close(mp->lcd) == -1)
    {
        perror("close ...");
        return false;
    }

    if(close(mp->ts) == -1)
    {
        perror("close ...");
        return false;
    }

    if(munmap(mp->mmap_start_poi,mp->lcd_w * mp->lcd_h * LCD_PIXEL_SIZE) == -1)
    {
        perror("munmap ...");
        return false;
    }

   //释放字符显示
    if(close(mp->dzk) == -1)
    {
        perror("close dzk...");
        return false;
    }

    if(munmap(mp->dzk_mmap_poi,mp->dzk_file_size) == -1)
    {
        perror("munmap lcd...");
        return false;
    }

    free(mp);

    return true;
}